import OpenAI from 'openai';
import { BadRequestException, Inject, Injectable, StreamableFile } from '@nestjs/common';
import { RedisService } from '../redis/redis.service';
import { Observable } from 'rxjs';
import { ChatCompletionMessageParam } from 'openai/resources/chat';

export type OpenaiModelType = 'KIMI' | 'DEEPSEEK' | 'DOUBAO';

@Injectable()
export class OpenaiService {
  kimiOpenAI: OpenAI;
  deepSeekOpenAI: OpenAI;
  doubaoOpenAI: OpenAI;

  @Inject(RedisService)
  private readonly redisService: RedisService;

  tools: Array<{
    type: 'function';
    function: {
      name: string;
      description?: string;
      parameters?: {
        type: 'object';
        properties: Record<string, any>;
        required?: string[];
        additionalProperties?: boolean;
      };
      strict?: boolean;
    };
  }> = [
    {
      type: 'function',
      function: {
        name: 'get_stock_dayline',
        description:
          '可以获取过去到最新的今年A股股票日线行情数据。返回数组，每个元素包含以下字段：ts_code(股票代码), trade_date(交易日期), open(开盘价), high(最高价), low(最低价), close(收盘价), pre_close(昨收价/前复权), change(涨跌额), pct_chg(涨跌幅%), vol(成交量手), amount(成交额千元)',
        parameters: {
          type: 'object',
          properties: {
            stock_code: {
              type: 'string',
              description: '股票代码，如688256.SH',
            },
            start_date: {
              type: 'string',
              description: '开始日期，格式YYYYMMDD，如20240101',
            },
            end_date: {
              type: 'string',
              description: '结束日期，格式YYYYMMDD，如20241231',
            },
          },
          required: ['stock_code', 'start_date', 'end_date'],
          additionalProperties: false,
        },
        strict: true,
      },
    },
  ];

  constructor() {
    this.kimiOpenAI = new OpenAI({
      baseURL: 'https://api.moonshot.cn/v1',
      apiKey: process.env.OPENAI_KIMI_API_KEY,
    });
    this.deepSeekOpenAI = new OpenAI({
      baseURL: 'https://api.deepseek.com',
      apiKey: process.env.OPENAI_DEEPSEEK_API_KEY,
    });
    this.doubaoOpenAI = new OpenAI({
      baseURL: 'https://ark.cn-beijing.volces.com/api/v3',
      apiKey: process.env.OPENAI_DOUBAO_API_KEY,
    });
  }

  async excuteDoubao(
    messages: ChatCompletionMessageParam[],
    modeleType: 'doubao1.6-thinking' | 'doubao1.6' | 'doubao1.6-flash' = 'doubao1.6-thinking',
    isJson: boolean = true,
  ) {
    try {
      const modelMap = {
        'doubao1.6': 'doubao-seed-1-6-250615',
        'doubao1.6-thinking': 'doubao-seed-1-6-thinking-250615',
        'doubao1.6-flash': 'doubao-seed-1-6-flash-250615',
      };
      const completion = await this.doubaoOpenAI.chat.completions.create({
        model: modelMap[modeleType],
        messages,
        response_format: isJson ? { type: 'json_object' } : undefined,
      });
      const content = completion.choices[0].message.content as string;
      console.log(
        `${modeleType} 本次分析消耗总Token ${completion.usage?.total_tokens}, 输入：${completion.usage?.prompt_tokens}, 输出：${completion.usage?.completion_tokens}`,
      );

      return isJson ? (JSON.parse(content ?? '{}') as Record<string, any>) : content;
    } catch (error) {
      console.log('DOUBAO 执行失败', error.message);
      return isJson ? {} : '';
    }
  }

  async excuteDeepSeek(
    messages: ChatCompletionMessageParam[],
    isJson: boolean = false,
    modeleType: 'deepseek-reasoner' = 'deepseek-reasoner',
  ) {
    try {
      const completion = await this.deepSeekOpenAI.chat.completions.create({
        model: modeleType,
        messages,
        response_format: isJson ? { type: 'json_object' } : undefined,
      });
      const content = completion.choices[0].message.content as string;
      console.log(
        `${modeleType} 本次分析消耗总Token ${completion.usage?.total_tokens}, 输入：${completion.usage?.prompt_tokens}, 输出：${completion.usage?.completion_tokens}`,
        // @ts-ignore
        `命中缓存：${completion.usage?.prompt_cache_hit_tokens}, 未命中缓存：${completion.usage?.prompt_cache_miss_tokens}`,
      );
      return isJson ? (JSON.parse(content ?? '{}') as Record<string, any>) : content;
    } catch (error) {
      console.log('DEEPSEEK 执行失败', error.message);
      return isJson ? {} : '';
    }
  }

  async createCompletion(key: string, defaultPrompt: { role: string; content: string }[], temperature = 0.3) {
    // 1 获取缓存
    let cacheMessages = await this.redisService.lrange(key, 0, -1);
    // 2 缓存不存在
    if (cacheMessages.length === 0) {
      await this.redisService.rpush(key, ...defaultPrompt.map((item) => JSON.stringify(item)));
      await this.redisService.setWithTTL(key, 10 * 60);
    }
    if (cacheMessages.length > process.env.OPENAI_MESSAGE_COUNT) {
      throw new BadRequestException('对话次数超过限制，请切换新的关键词重新生成');
    }
    // 3 添加用户消息analysisFields
    await this.redisService.rpush(key, JSON.stringify({ role: 'user', content: '生成一条' }));
    // 4 获取对话
    cacheMessages = await this.redisService.lrange(key, 0, -1);
    // 4 创建对话
    const completion = await this.deepSeekOpenAI.chat.completions.create({
      // model: 'moonshot-v1-8k',
      model: 'deepseek-chat',
      messages: cacheMessages.map((item) => JSON.parse(item)),
      temperature: temperature,
      stream: true,
      stream_options: {},
    });
    // 5 创建一个增强的流，在传输的同时收集完整内容
    let fullContent = '';
    const stream = new Observable((observer) => {
      (async () => {
        try {
          for await (const chunk of completion) {
            const content = chunk.choices[0]?.delta?.content || '';
            fullContent += content;
            observer.next({ end: false, msg: content });
          }
          // 流结束后，存储完整对话到Redis
          await this.redisService.rpush(
            key,
            JSON.stringify({
              role: 'assistant',
              content: fullContent,
            }),
          );
          observer.next({ end: true });
          observer.complete();
        } catch (error) {
          observer.error(error);
        }
      })();
    });

    return stream;
  }
}
